package com.example.shiroredis.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.shiroredis.properties.SpringProperties;
import com.example.shiroredis.utils.ShiroUtils;
import com.example.shiroredis.utils.ThreadLocalMap;
import com.example.shiroredis.utils.ValidatedUtils;
import com.example.shiroredis.utils.jwt.JwtUtils;
import com.example.shiroredis.entity.MpUserInfo;
import com.example.shiroredis.entity.base.ResultCode;
import com.example.shiroredis.entity.base.ResultObj;
import com.example.shiroredis.service.inter.MpUserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.Serializable;
import java.util.List;

/**
 * @Author: lex
 * @Date: 2018/11/14
 */
@RestController
@RequestMapping("shiro/mp")
@Slf4j
public class UserController {

    @Autowired
    private SpringProperties springProperties;

    @Autowired
    private MpUserInfoService mpUserInfoService;

    @PostMapping("login")
    public ResultObj login(String username, String password) {
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return new ResultObj(407, "用户名或者密码不能为空");
        }
        Subject subject = SecurityUtils.getSubject();
        //封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            Serializable sessionId = ShiroUtils.getSession().getId();
            log.warn("sessionId=[ {} ] ", sessionId);
            String jwtToken = JwtUtils.createJWT(sessionId.toString(), ShiroUtils.getUser().toString(), springProperties.getRedis().getTimeout() * 1000);
            return new ResultObj().putData("user", ShiroUtils.getUser())
                    //将sessionId存到请求头Authorization中,
                    //MySessionManager对获得jsessionId进行重写,原本是从cookie中获取,现在从请求头中获得
                    .putData("Authorization", jwtToken);
        } catch (
                UnknownAccountException e) {
            //用户名不存在
            log.error("用户名不存在", e);
            return new ResultObj(407, "用户名不存在");
        } catch (
                LockedAccountException e) {
            log.error("管理员锁定/被删除", e);
            return new ResultObj(407, "管理员锁定/被删除");
        } catch (
                IncorrectCredentialsException e) {
            //用户名不存在
            log.error("密码错误", e);
            return new ResultObj(407, "密码错误");
        }
    }

    @PostMapping("setSession")
    public ResultObj setSession(String key, String value) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) {
            return new ResultObj(407, "key或者value不能为空");
        }
        ShiroUtils.setSessionAttribute(key, value);
        return new ResultObj();
    }

    @PostMapping("logout")
    public ResultObj logout() {
        ShiroUtils.logout();
        return new ResultObj();
    }

    @PostMapping("getSession")
    public ResultObj getSession(String key) {
        if (StringUtils.isBlank(key)) {
            return new ResultObj(407, "key不能为空");
        }
        //lex
        return new ResultObj().putData("key", ShiroUtils.getSessionAttribute(key));
    }

    @GetMapping("total")
    public ResultObj total() {
        System.out.println("ShiroUtils.getUser(): " + ShiroUtils.getUser());
        System.out.println("ShiroUtils.getUserId(): " + ShiroUtils.getUserId());
        System.out.println("ShiroUtils.getSession(): " + ShiroUtils.getSession());
        System.out.println("ShiroUtils.getSession().getId()(): " + ShiroUtils.getSession().getId());
        System.out.println("ShiroUtils.getSubject(): " + ShiroUtils.getSubject());
        return new ResultObj();
    }

    @RequiresPermissions(value = {"msg:find1231232134"})
    @GetMapping("total2")
    public ResultObj total2() {
        System.err.println("ShiroUtils.getUser(): " + ShiroUtils.getUser());
        System.err.println("ShiroUtils.getUserId(): " + ShiroUtils.getUserId());
        System.err.println("ShiroUtils.getSession(): " + ShiroUtils.getSession());
        System.err.println("ShiroUtils.getSession().getId()(): " + ShiroUtils.getSession().getId());
        System.err.println("ShiroUtils.getSubject(): " + ShiroUtils.getSubject());
        return new ResultObj();
    }

    @GetMapping("add2")
    public ResultObj add2() {
        MpUserInfo mpUserInfo = new MpUserInfo();
        mpUserInfo.setNickName("1232133213213");
        mpUserInfo.insert();
        return new ResultObj();
        //List<MpUserInfo> mpUserInfos = mpUserInfoService.list(null);
        //return new ResultObj().putData("mpUserInfos", mpUserInfos);
    }

    @GetMapping("nologinCode")
    public ResultObj nologinCode() {
        ResultCode errorMsg = (ResultCode) ThreadLocalMap.get("errorMsg");
        log.error("错误原因为:[{}]", errorMsg.getDesc());
        return new ResultObj(errorMsg);
    }

    @GetMapping("noAuthCode")
    public ResultObj noAuthCode() {
        return new ResultObj(407, "shiroConfig未授权配置经过的地方");
    }

    @GetMapping("add")
    public ResultObj add(@Validated MpUserInfo mpUserInfo, BindingResult result) {
        if (ValidatedUtils.errorResultMsg(result) != null) {
            return ValidatedUtils.errorResultMsg(result);
        }
        //lex
        mpUserInfo.insert();
        List<MpUserInfo> mpUserInfos = mpUserInfoService.list(null);
        return new ResultObj().putData("mpUserInfos", mpUserInfos);
    }


    @GetMapping("testService")
    public ResultObj testService() {
        System.out.println(ShiroUtils.getSession().getId());
        System.err.println("testService");
        List<MpUserInfo> mpUserInfos = mpUserInfoService.list(null);
        return new ResultObj().putData("mpUserInfos", mpUserInfos);
    }

    @GetMapping("testServicePage")
    public ResultObj testServicePage() {
        IPage<MpUserInfo> page = mpUserInfoService.page(new Page<>(1, 10), null);
        return new ResultObj().putData("list", page.getRecords())
                .putData("total", page.getTotal())
                .putData("pages", page.getPages());
    }

    @GetMapping("testEntityPage")
    @Cacheable(value = "LINENXITEST", key = "'testEntityPage'")
    public ResultObj testEntityPage() {
        IPage<MpUserInfo> page = new MpUserInfo().selectPage(new Page<>(1, 10), null);
        return new ResultObj().putData("list", page.getRecords())
                .putData("total", page.getTotal())
                .putData("pages", page.getPages());
    }

    @GetMapping("setLINENXI")
    public ResultObj setLINENXI(String key, String value) {
        return new ResultObj();
    }

    @GetMapping("getLINENXI")
    public ResultObj getLINENXI(String key) {
        return new ResultObj();
    }

    @GetMapping("closetestEntityPage")
    @CacheEvict(value = "LINENXITEST", allEntries = true)
    public ResultObj closetestEntityPage() {
        return new ResultObj();
    }

    @GetMapping("closetestEntityPage2")
    @CacheEvict(allEntries = true)
    public ResultObj closetestEntityPage2() {
        return new ResultObj();
    }

    //@GetMapping("testEntity")
    //public ResultObj testEntity() {
    //    System.err.println("testEntity");
    //    List<MpUserInfo> mpUserInfos = new MpUserInfo().selectList(null);
    //    return new ResultObj().putData("mpUserInfos", mpUserInfos);
    //}
    //@GetMapping("login")
    //public ResultObj login() {
    //    return new ResultObj(407, "这是登入页面");
    //}
    ////
    //@PostMapping("addUser")
    //public ResultObj addUser(MpUserInfo mpUserInfo) {
    //    mpUserInfoService.save
    //    mpUserInfo.insert();
    //    return new ResultObj();
    //}
    //
    //@PostMapping("updateUser")
    //public ResultObj updateUser(MpUserInfo mpUserInfo) {
    //    if (mpUserInfo.getId() == null) {
    //        return new ResultObj(407, "id没传");
    //    }
    //    mpUserInfo.updateById();
    //    return new ResultObj();
    //}
    //
    @PostMapping("logicDeleteById")
    public ResultObj logicDeleteById(long id) {
        MpUserInfo mpUserInfo = new MpUserInfo();
        mpUserInfo.setId(id);
        if (mpUserInfo.getId() == null) {
            return new ResultObj(407, "id没传");
        }
        mpUserInfo.setIsDelete((short) 1);
        mpUserInfoService.updateById(mpUserInfo);
        return new ResultObj();
    }

    @PostMapping("deleteById")
    public ResultObj deleteById(long id) {
        mpUserInfoService.removeById(id);
        return new ResultObj();
    }

    @GetMapping("getOne")
    public ResultObj getOne() {
        MpUserInfo one = mpUserInfoService.getOne(null, true);
        return new ResultObj().putData("one", one);
    }

    @GetMapping("query")
    public ResultObj query(MpUserInfo mpUserInfo) {
        MpUserInfo one = mpUserInfoService.query(mpUserInfo);
        return new ResultObj().putData("one", one);
    }

    @GetMapping("deleteOne")
    public ResultObj deleteOne(long id) {
        mpUserInfoService.removeById(id);
        return new ResultObj();
    }

    @GetMapping("pageEntity")
    public ResultObj pageEntity(Integer page, Integer pageSize, MpUserInfo mpUserInfo) {
        IPage<MpUserInfo> Ipage = mpUserInfoService.pageEntity(page, pageSize, mpUserInfo);
        return new ResultObj().putData("list", Ipage.getRecords())
                .putData("total", Ipage.getTotal())
                .putData("pages", Ipage.getPages());
    }

    @GetMapping("listEntity")
    public ResultObj listEntity(MpUserInfo mpUserInfo) {
        List<MpUserInfo> mpUserInfos = mpUserInfoService.listEntity(mpUserInfo);
        return new ResultObj().putData("mpUserInfos", mpUserInfos);
    }

    @GetMapping("listMe")
    public ResultObj listMe(MpUserInfo mpUserInfo) {
        List<MpUserInfo> mpUserInfos = mpUserInfo.selectList(new QueryWrapper());
        return new ResultObj().putData("mpUserInfos", mpUserInfos);
    }

    @GetMapping("getShiroUser")
    public ResultObj getShiroUser(){
        return new ResultObj().putData("user", ShiroUtils.getUser());
    }
}
